package com.hyt.it.ogt.ykcj.service.exchange.impl;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.it.ogt.data.service.kwgov.IKwGovTaskService;
import com.hyt.it.ogt.pj.mapper.ProjectMapper;
import com.hyt.it.ogt.pj.service.IStudentAnswerService;
import com.hyt.it.ogt.ykcj.common.enums.CommonEnums;
import com.hyt.it.ogt.ykcj.common.enums.ExchangeNameEnum;
import com.hyt.it.ogt.ykcj.common.enums.ExchangeValTypeEnum;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.IdUtils;
import com.hyt.it.ogt.ykcj.domain.exam.CandidateConfig;
import com.hyt.it.ogt.ykcj.domain.exam.CandidateInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamNameConfig;
import com.hyt.it.ogt.ykcj.domain.exam.ExamStemInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectNameConfig;
import com.hyt.it.ogt.ykcj.domain.exchange.ExamineeExamInfo;
import com.hyt.it.ogt.ykcj.domain.exchange.ExchangeCandidate;
import com.hyt.it.ogt.ykcj.domain.exchange.ExchangeCandidateConfig;
import com.hyt.it.ogt.ykcj.domain.exchange.ExchangeCandidateInfo;
import com.hyt.it.ogt.ykcj.domain.exchange.ExchangeStem;
import com.hyt.it.ogt.ykcj.domain.exchange.ExchangeSubjectInfo;
import com.hyt.it.ogt.ykcj.domain.grade.EnterpriseExamineeInfo;
import com.hyt.it.ogt.ykcj.domain.grade.EnterpriseExamineeSubjectGrade;
import com.hyt.it.ogt.ykcj.domain.param.EnterpriseScoreLineSaveParam;
import com.hyt.it.ogt.ykcj.domain.param.ScoreLineItem;
import com.hyt.it.ogt.ykcj.domain.vo.ExamExamineeSubjectVo;
import com.hyt.it.ogt.ykcj.feign.kw.ExamClient;
import com.hyt.it.ogt.ykcj.feign.model.CandidateAnswersResultEntity;
import com.hyt.it.ogt.ykcj.feign.model.ResultEntity;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamStemInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.exchange.CandidateConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.exchange.CandidateInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.EnterpriseExamineeInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.EnterpriseExamineeSubjectGradeMapper;
import com.hyt.it.ogt.ykcj.service.exam.IEnterpriseExamScoreLineSettingService;
import com.hyt.it.ogt.ykcj.service.exchange.IExamineeExamInfoService;
import com.hyt.it.ogt.ykcj.service.exchange.IExchangeCandidateService;
import com.hyt.it.ogt.ykcj.service.system.ISysDictDataService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * description 考生配置Service业务层处理
 * 这里是一个考试任务下多个批次的处理，里面的额注释都用的以前的，可能没修改，请谨慎！！！
 *
 * @author yaojian
 * @createTime 2021/12/03
 */
@Slf4j
@Service
public class ExchangeCandidateServiceImpl implements IExchangeCandidateService {

    @Resource
    private ExamInfoMapper examInfoMapper;
    @Resource
    private CandidateConfigMapper candidateConfigMapper;
    @Resource
    private CandidateInfoMapper candidateInfoMapper;
    @Resource
    private ExamSubjectInfoMapper examSubjectInfoMapper;
    @Resource
    private ExamStemInfoMapper examStemInfoMapper;
    @Resource
    private EnterpriseExamineeSubjectGradeMapper enterpriseExamineeSubjectGradeMapper;
    @Resource
    private ExamSubjectNameConfigMapper examSubjectNameConfigMapper;
    @Resource
    private ExamNameConfigMapper examNameConfigMapper;
    @Resource
    private EnterpriseExamineeInfoMapper enterpriseExamineeInfoMapper;
    @Resource
    private IEnterpriseExamScoreLineSettingService enterpriseExamScoreLineSettingService;
    @Resource
    private ExamClient examClient;
    @Resource
    private ISysDictDataService dictDataService;
    @Resource
    private IExamineeExamInfoService examineeExamInfoService;
    @Resource
    private IKwGovTaskService iKwGovTaskService;
    @Resource
    private IStudentAnswerService iStudentAnswerService;
    @Resource
    private ProjectMapper projectMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExamExamineeSubjectVo saveCandidateInfo(ExchangeCandidate exchangeCandidate) {
        // 二次处理接口数据
        exchangeCandidate.setCurrExamId(exchangeCandidate.getExamId());
        if (StringUtils.isEmpty(exchangeCandidate.getTestClassify())) {
            exchangeCandidate.setTestClassify(CommonEnums.EXAM_TYPE_OTHER.getCode());
        } else {
            String[] split = exchangeCandidate.getTestClassify().split(",");
            exchangeCandidate.setTestClassify(split[split.length - 1]);
        }

        /**
         * 因为这个保存学生考生内容的方法过于复杂，所以在这里全部把存在的情况列举出来
         *
         * *************************【一个考生的成绩数据推过来】**************
         *
         * 一：先判断这个考试是否在我们这边存在，存在：拉取后更新，不存在：拉取后插入
         *    1.1:如果考试下的所有学生已经归档，那么再推送成绩不不会再保存
         *          (改为：当前考生如果归档就不进行再次保存了)
         *    1.2:如果存在归档的考生或者归档的科目，那么就不要更新总分分数线了;如果有归档的科目，那么就不要更新总分分数线了
         * 二：获取要保存考生信息
         * 三：考生的信息设置完成后要进行成绩和科目和大题的遍历，在此之前保存一个科目的分数线对象和一些全局的对象
         * 四：获取科目信息，进行操作
         *    4.0:判断是否保存最高的分数线,4.1：考生有：1：新推送的考试数据，2：老数据重复推送，3：更新推送   要分别进行整理出来
         * 五：获取要保存科目和科目名称及科目下的大题信息
         *   科目有两种情况，新增和修改
         *    5.1：获取已存在的科目中科目的大题信息,在数据库中查询看是否存在，如果存在：不处理，如果不存在：进行保存
         *    5.2：获取新增科目的大题信息和科目大题的分数对象
         * 六：保存复合分数信息
         * 七：保存考生信息，如果考生存在，则删除成绩后再添加信息，如果不存在，则保存成绩信息
         * 八：先清除考生的考成绩，然后保存考生的考试成绩
         *
         *
         */
        ExamInfo currExamInfo = new ExamInfo();
        if (exchangeCandidate.getExamId() == null) {
            throw new CustomException("考试id不能为空!");
        }
        //如果是无考场考试，
        if (StringUtils.isNotEmpty(exchangeCandidate.getTaskId())) {
            currExamInfo.setExamCode(exchangeCandidate.getExamId());
            currExamInfo.setTaskId(exchangeCandidate.getTaskId());
            exchangeCandidate.setExamCode(exchangeCandidate.getExamId());
        } else {
            //INFO 从考试系统中来的考试id在成绩系统中存为考试code
            exchangeCandidate.setExamCode(exchangeCandidate.getExamId());
        }

        //一： 获取考试信息，进行操作
        //1：获取保存考试信息（先根据id查询看是否存在考试，不存在：获取考试内容，进行保存，存在：获取考试内容进行根据）
        String examCode = exchangeCandidate.getExamCode();
        ExamInfo examInfo = examInfoMapper.selectExamInfoByCode(examCode);

        ResultEntity resultEntity = examClient.getExamInfo(exchangeCandidate.getExamCode());
        log.info("远程获取到考试考生信息资源是{}", FastJsonUtil.getBeanToJson(resultEntity));

        if (examInfo == null || StringUtils.isEmpty(examInfo.getId())) {
            // 入股考务获取数据不到或者失败，则直接中断保存
            if (resultEntity.getCode() != Integer.parseInt(CommonEnums.EXAMSYS_RESULT_CODE.getCode()) && resultEntity.getCode() != Integer.parseInt(CommonEnums.EXAMSYS_RESULT_CODE_V2.getCode())) {
                throw new CustomException("无法获取考试信息！");
            }
            //保存考试名称信息
            String examNameConfigId = IdUtils.generateId();

            ExamNameConfig examNameConfig = getUpdateExamNameConfig(resultEntity.getData().getExam().getExamName(), examNameConfigId, exchangeCandidate);
            examNameConfigMapper.insertExamNameConfig(examNameConfig);
            //保存考试信息
            //考试id设置
            String examId = "KS" + IdUtils.generateId();
            exchangeCandidate.setExamId(examId);
            String examInfoCode = currExamInfo.getExamCode();
            currExamInfo.setExamStartDay(resultEntity.getData().getExam().getBeginDate());
            currExamInfo.setExamEndDay(resultEntity.getData().getExam().getEndDate());
            currExamInfo = getExamInfo(exchangeCandidate, resultEntity.getData().getExam().getBeginDate(), resultEntity.getData().getExam().getEndDate(), examNameConfigId);
            examInfoMapper.insertExamInfo(currExamInfo);
            currExamInfo.setExamCode(examInfoCode);
        } else {
            //更新考试名称
            ExamNameConfig examNameConfig = getUpdateExamNameConfig(examInfo, resultEntity.getData().getExam().getExamName(), exchangeCandidate);
            examNameConfigMapper.updateExamNameConfig(examNameConfig);
            //更新考试信息
            String examInfoCode = examInfo.getExamCode();
            currExamInfo = getUpdataExamInfo(exchangeCandidate, resultEntity.getData().getExam().getBeginDate(), resultEntity.getData().getExam().getEndDate(),  examInfo);
            currExamInfo.setExamStartDay(resultEntity.getData().getExam().getBeginDate());
            currExamInfo.setExamEndDay(resultEntity.getData().getExam().getEndDate());
            examInfoMapper.updateExamInfo(currExamInfo);
            exchangeCandidate.setExamId(examInfo.getId());
            currExamInfo.setExamCode(examInfoCode);
        }

        //改为：当前考生如果归档就不进行再次保存了
        EnterpriseExamineeInfo selectExaminee = enterpriseExamineeInfoMapper.selectEnterpriseExamineeInfoById(exchangeCandidate.getCandidateId());
        if (selectExaminee != null && selectExaminee.getArchivedStatus().equals(CommonEnums.ARCHIVED_STATUS_Y.getCode())) {
            throw new CustomException("当前考生已归档，无法再次更新保存！");
        }

        //一:（1） 考生如果全部归档，就不进行任何保存,如果
        //一:（2）如果存在归档的考生或者归档的科目，那么就不要更新总分分数线了
        EnterpriseExamineeInfo countEnterpriseExamineeInfo = new EnterpriseExamineeInfo();
        countEnterpriseExamineeInfo.setExamId(currExamInfo.getId());
        countEnterpriseExamineeInfo.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_Y.getCode());
        countEnterpriseExamineeInfo.setOfficeId(exchangeCandidate.getOfficeId());
        countEnterpriseExamineeInfo.setDeptId(exchangeCandidate.getDeptId());
        int archivedNum = enterpriseExamineeInfoMapper.selectEnterpriseExamineeInfoCount(countEnterpriseExamineeInfo);
        boolean saveScoreLine = true;
        if (archivedNum > 0) {
            saveScoreLine = false;
        }
        // 如果有归档的科目，那么就不要更新总分分数线了
        Integer archivesubjectCount = enterpriseExamineeSubjectGradeMapper.countArchivedExamineeSubject(currExamInfo.getId());
        if (archivesubjectCount > 0) {
            saveScoreLine = false;
        }

        //二：获取要保存考生信息（包括考生，考生配置信息，考生配置信息详情对象），进行操作
        //二：（1）获取要保存的考生对象
        EnterpriseExamineeInfo examinee = getExaminee(exchangeCandidate);
        EnterpriseExamineeInfo enterpriseExamineeInfo = enterpriseExamineeInfoMapper.selectEnterpriseExamineeInfoById(examinee.getId());

        // 获取考生信息、考生信息详情配置的对象信息对象
        List<CandidateConfig> candidateConfigs = new ArrayList<>();
        List<CandidateInfo> candidateInfos = new ArrayList<>();
        getCandidateAllData(exchangeCandidate, examinee, candidateConfigs, candidateInfos);

        // 保存考生的信息（删除考生的配置信息，再添加配置信息）
        if (CollectionUtils.isNotEmpty(candidateConfigs)) {
            candidateConfigMapper.deleteByCondition(candidateConfigs, examinee.getId());
            candidateConfigMapper.saveBatch(candidateConfigs);
        }
        if (CollectionUtils.isNotEmpty(candidateInfos)) {
            candidateInfoMapper.deleteByCondition(candidateInfos.get(0));
            candidateInfoMapper.saveBatch(candidateInfos);
        }

        //三：设置复合分数线对象
        EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam = new EnterpriseScoreLineSaveParam();
        enterpriseScoreLineSaveParam.setType(CommonEnums.SCORE_LINE_TYPE_1.getCode());
        enterpriseScoreLineSaveParam.setExamId(exchangeCandidate.getExamId());
        enterpriseScoreLineSaveParam.setComparisonType(CommonEnums.COMPARISON_TYPE_1.getCode());
        enterpriseScoreLineSaveParam.setCompositeScore(exchangeCandidate.getScoreLine().toString());
        enterpriseScoreLineSaveParam.setDimension(CommonEnums.SCORE_LINE_DIMENSION_0.getCode());

        //四：获取科目信息，进行操作
        //四：(0)判断是否保存最高的分数线：
        List<ExchangeSubjectInfo> allExchangeSubjectInfo = exchangeCandidate.getSubjectInfo();
        // 提出掉非普通卷的科目类型
        for (Iterator<ExchangeSubjectInfo> iterator = allExchangeSubjectInfo.iterator(); iterator.hasNext(); ) {
            ExchangeSubjectInfo exchangeSubjectInfo = iterator.next();
            if (exchangeSubjectInfo.getSubjectType().equals(Integer.valueOf(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode()))) {
                iterator.remove();
            }
        }
        BigDecimal allScore = new BigDecimal("0");
        for (ExchangeSubjectInfo exchangeSubjectInfo : allExchangeSubjectInfo) {
            if (null != exchangeSubjectInfo.getPapertScore()) {
                allScore = allScore.add(exchangeSubjectInfo.getPapertScore());
            }
        }
        //&& allScore.compareTo(enterpriseExamineeInfo.getAllScore()) == -1
        if (enterpriseExamineeInfo != null && enterpriseExamineeInfo.getAllScore() != null) {
            if (examinee.getKeepHighestScore() && allScore.compareTo(enterpriseExamineeInfo.getAllScore()) < 0) {
                return new ExamExamineeSubjectVo();
            }
        }
        examinee.setAllScore(allScore);


        //四：（1）获取新增和老的的科目列表，并设置复合分数线
        List<ExchangeSubjectInfo> newExchangeSubjectInfo = new ArrayList<>();
        List<ExchangeSubjectInfo> oldExchangeSubjectInfo = new ArrayList<>();
        List<ScoreLineItem> scoreLineItems = new ArrayList<>();
        getDistSubjectInfo(exchangeCandidate, newExchangeSubjectInfo, oldExchangeSubjectInfo, scoreLineItems);
        //把老的科目的总分和合格分数线设置最高的那个分数
        if (CollectionUtils.isNotEmpty(oldExchangeSubjectInfo)) {
            examSubjectInfoMapper.updataBatchSubjectFullScore(oldExchangeSubjectInfo);
        }

        //五：获取要保存科目和科目名称
        List<ExamSubjectInfo> saveExamSubjectInfoList = new ArrayList<>();
        List<ExamSubjectNameConfig> saveExamSubjectNameConfigList = new ArrayList<>();
        getExamSubjectInfo(exchangeCandidate, newExchangeSubjectInfo, saveExamSubjectInfoList, saveExamSubjectNameConfigList);
        //把新增的科目和科目名称进行保存
        if (CollectionUtils.isNotEmpty(saveExamSubjectInfoList)) {
            examSubjectInfoMapper.saveBatch(saveExamSubjectInfoList);
        }
        if (CollectionUtils.isNotEmpty(saveExamSubjectNameConfigList)) {
            examSubjectNameConfigMapper.saveBatch(saveExamSubjectNameConfigList);
        }

        //五：（1）获取已存在的科目中科目的大题信息,在数据库中查询看是否存在，如果存在：不处理，如果不存在：进行保存，要保存的新的大题存放老的科目总的新的大题和新的科目中的新的大题
        List<ExamStemInfo> saveExamStemInfo = new ArrayList<>();
        //获取老的科目中的新的大题
        List<ExchangeStem> oldExchangeSubjectStemList = new ArrayList<>();
        if (CollUtil.isNotEmpty(oldExchangeSubjectInfo)) {
            oldExchangeSubjectInfo.forEach(oldTempExchangeSubjectInfo -> {
                if (CollUtil.isNotEmpty(oldTempExchangeSubjectInfo.getStemList())) {
                    oldExchangeSubjectStemList.addAll(oldTempExchangeSubjectInfo.getStemList());
                }
            });
        }

        if (CollUtil.isNotEmpty(oldExchangeSubjectStemList)) {
            List<ExamStemInfo> oldSubjectStemList = examStemInfoMapper.selectExamStemBySujectIdAndStemCode(exchangeCandidate.getExamId(), oldExchangeSubjectStemList);
            for (ExchangeStem exchangeStem : oldExchangeSubjectStemList) {
                //如果存这个题目在则不进行保存处理
                boolean exit = false;
                for (ExamStemInfo tempExamStemInfo : oldSubjectStemList) {
                    if (exchangeStem.getStemId().equals(tempExamStemInfo.getStemCode())) {
                        exit = true;
                        break;
                    }
                }
                //存在了这个大题，就不进行新增处理
                if (!exit) {
                    getSaveExamStemInfo(exchangeCandidate, saveExamStemInfo, exchangeStem);
                }
            }
        }
        //五：（2）获取新增科目的大题信息和科目大题的分数对象
        List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeList = new ArrayList<>();
        List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeListNoPersonality = new ArrayList<>();
        getSubjectStemInfo(exchangeCandidate, newExchangeSubjectInfo, examineeSubjectGradeList, examineeSubjectGradeListNoPersonality, saveExamStemInfo);

        //获取老的题目分数
        getSubjectAndStemInfo(exchangeCandidate, oldExchangeSubjectInfo, examineeSubjectGradeList, examineeSubjectGradeListNoPersonality, saveExamStemInfo);
        // 对需要新增的考试题干信息入库
        if (CollectionUtils.isNotEmpty(saveExamStemInfo)) {
            examStemInfoMapper.insertBatchExamStemInfo(saveExamStemInfo);
        }

        //六：保存复合分数信息 设置分数线
        enterpriseScoreLineSaveParam.setScoreLineItems(scoreLineItems);
        //1:如果分数线为0，则表示不需要保存复合分数线,
        //2:如果总分的分数大于等于科目的总分分数，则不保存总分的复合分数线,
        //3:如果已经归档了学生，那么分数就不需要再保存了
        if (!exchangeCandidate.getScoreLine().equals(BigDecimal.ZERO) && saveScoreLine && exchangeCandidate.getScoreLine().compareTo(exchangeCandidate.getSubjectTotleScore()) < 1) {
            List<String> strings = enterpriseExamScoreLineSettingService.selectScoreLineIds(enterpriseScoreLineSaveParam.getExamId(), CommonEnums.SCORE_LINE_TYPE_1.getCode(), CommonEnums.SCORE_LINE_DIMENSION_0.getCode());
            // 如果存在复合分数线，那么就追加
            if (CollectionUtils.isNotEmpty(strings)) {
                enterpriseExamScoreLineSettingService.addToScoreLine(enterpriseScoreLineSaveParam);
            } else {
                enterpriseExamScoreLineSettingService.createScoreLine(enterpriseScoreLineSaveParam);
            }
        }
        ///////////////////////////////////////////////设置考试的复合分数线///////////////////////////////////////////////

        //如果考试存在性格卷，则不设置考生成绩合格字段
        examinee.setQualifiedStatus("");

        //七：保存考生信息，如果考生存在，则删除成绩后再添加信息，如果不存在，则保存成绩信息
        if (enterpriseExamineeInfo == null || StringUtils.isEmpty(enterpriseExamineeInfo.getId())) {
            enterpriseExamineeInfoMapper.insertEnterpriseExamineeInfo(examinee);
        } else {
            enterpriseExamineeInfo.setId(enterpriseExamineeInfo.getId());
            enterpriseExamineeInfoMapper.updateEnterpriseExamineeInfo(examinee);
        }

        //八：先清除考生的考试成绩，然后保存考生的考试成绩
        enterpriseExamineeSubjectGradeMapper.deleteBatchByExamIdAndExamineeId(exchangeCandidate.getExamId(), exchangeCandidate.getCandidateId());
        if (CollectionUtils.isNotEmpty(examineeSubjectGradeList)) {
            enterpriseExamineeSubjectGradeMapper.insertBatchEnterpriseExamineeSubjectGrade(examineeSubjectGradeList);
        }

        log.info("保存的数据对象json内容是:{}", JSON.toJSONString(exchangeCandidate, SerializerFeature.DisableCircularReferenceDetect));

        //九，拉取考生考试的内容进行保存
        CandidateAnswersResultEntity candidateAnswersResult = examClient.queryCandidateAnswers(exchangeCandidate.getCurrExamId(), examinee.getId());

        log.info("拉取的考试试卷内容是:{}", JSON.toJSONString(candidateAnswersResult, SerializerFeature.DisableCircularReferenceDetect));
        String answerJson = JSON.toJSONString(candidateAnswersResult.getData(), SerializerFeature.DisableCircularReferenceDetect);
        ExamineeExamInfo examineeExamInfo = new ExamineeExamInfo();
        examineeExamInfo.setId(IdUtils.generateId());
        examineeExamInfo.setExamId(currExamInfo.getId());
        examineeExamInfo.setExamineeId(examinee.getId());
        examineeExamInfo.setExamineeExamInfo(answerJson);
        examineeExamInfo.setPaperId(candidateAnswersResult.getData().getPaperId());
        examineeExamInfoService.saveOrUpdate(examineeExamInfo);

        ExamExamineeSubjectVo examExamineeSubjectVo = new ExamExamineeSubjectVo();
        examExamineeSubjectVo.setExamId(currExamInfo.getId());
        examExamineeSubjectVo.setExamineeId(examinee.getId());
        return examExamineeSubjectVo;
    }
    


    /**
     * 把要保存的大题信息添加到要保存的list中
     *
     * @param exchangeCandidate
     * @param saveExamStemInfo
     * @param exchangeStem
     */
    private void getSaveExamStemInfo(ExchangeCandidate exchangeCandidate, List<ExamStemInfo> saveExamStemInfo, ExchangeStem exchangeStem) {
        ExamStemInfo examStemInfo = new ExamStemInfo();
        String stemId = IdUtils.generateId();
        examStemInfo.setId(stemId);
        examStemInfo.setStemCode(exchangeStem.getStemId());
        examStemInfo.setName(exchangeStem.getStemName());
        examStemInfo.setSubjectId(exchangeStem.getSubjectId());
        examStemInfo.setTitleNumber(0);
        examStemInfo.setSort(0);
        examStemInfo.setTotalPoints(new BigDecimal(0));
        examStemInfo.setDeptId(exchangeCandidate.getDeptId());
        examStemInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        examStemInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        examStemInfo.setCreateTime(new Date());
        examStemInfo.setUpdateTime(new Date());
        examStemInfo.setOfficeId(exchangeCandidate.getOfficeId());
        saveExamStemInfo.add(examStemInfo);
    }

    /**
     * 获取老题目分数(已经存在的科目只要获取科目成绩和题目成绩就行了)
     *
     * @param exchangeCandidate
     * @param oldExchangeSubjectInfo
     * @param examineeSubjectGradeList
     */
    private void getSubjectAndStemInfo(ExchangeCandidate exchangeCandidate, List<ExchangeSubjectInfo> oldExchangeSubjectInfo,
                                       List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeList,
                                       List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeListNoPersonality,
                                       List<ExamStemInfo> saveExamStemInfo) {
        List<String> subjectIdList = new ArrayList<>();
        exchangeCandidate.getSubjectInfo().forEach(exchangeSubjectInfo -> {
            subjectIdList.add(exchangeSubjectInfo.getId());
        });
        //获取所有大题对应的科目
        List<ExamStemInfo> tempOldexamStemInfoList = examStemInfoMapper.selectOldStem(exchangeCandidate.getExamId(), subjectIdList);
        List<ExamStemInfo> oldexamStemInfoList = new ArrayList<>();
        for (ExamStemInfo examStemInfo : tempOldexamStemInfoList) {
            if (examStemInfo != null && StringUtils.isNotEmpty(examStemInfo.getStemCode())) {
                oldexamStemInfoList.add(examStemInfo);
            }
        }
        //这些大题中的科目可能存在是不同试卷来的大题，所有要混入可能需要保存的大题内容来给大题匹配对应的科目id
        oldexamStemInfoList.addAll(saveExamStemInfo);

        oldExchangeSubjectInfo.stream().forEach(exchangeSubjectInfo -> {
            //获取科目的分数
            EnterpriseExamineeSubjectGrade enterpriseExamineeSubjectGrade = new EnterpriseExamineeSubjectGrade();
            enterpriseExamineeSubjectGrade.setId(IdUtils.generateId());
            enterpriseExamineeSubjectGrade.setExamId(exchangeCandidate.getExamId());
            enterpriseExamineeSubjectGrade.setExamineeId(exchangeCandidate.getCandidateId());
            enterpriseExamineeSubjectGrade.setSubjectId(exchangeSubjectInfo.getId());
            enterpriseExamineeSubjectGrade.setStemId("");
            enterpriseExamineeSubjectGrade.setUseTime(exchangeSubjectInfo.getPaperUseTime());
            enterpriseExamineeSubjectGrade.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_N.getCode());
            enterpriseExamineeSubjectGrade.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            enterpriseExamineeSubjectGrade.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            enterpriseExamineeSubjectGrade.setCreateTime(new Date());
            enterpriseExamineeSubjectGrade.setUpdateTime(new Date());
            enterpriseExamineeSubjectGrade.setQualifiedStatus("");
            enterpriseExamineeSubjectGrade.setOfficeId(exchangeCandidate.getOfficeId());
            enterpriseExamineeSubjectGrade.setDeptId(exchangeCandidate.getDeptId());
            if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_1.getCode())) {
                //普通科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_2.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode())) {
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_1.getCode());
                enterpriseExamineeSubjectGrade.setScore(null);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_3.getCode())) {
                //编程科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_3.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_5.getCode())) {
                //单题计时卷科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_5.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            }

            examineeSubjectGradeList.add(enterpriseExamineeSubjectGrade);
            if (CollectionUtils.isNotEmpty(exchangeSubjectInfo.getStemList())) {
                for (ExchangeStem exchangeStem : exchangeSubjectInfo.getStemList()) {
                    //获取题目的得分
                    EnterpriseExamineeSubjectGrade enterpriseExamineeSubjectStemGrade = new EnterpriseExamineeSubjectGrade();
                    enterpriseExamineeSubjectStemGrade.setId(IdUtils.generateId());
                    enterpriseExamineeSubjectStemGrade.setExamId(exchangeCandidate.getExamId());
                    enterpriseExamineeSubjectStemGrade.setExamineeId(exchangeCandidate.getCandidateId());
                    enterpriseExamineeSubjectStemGrade.setSubjectId(exchangeSubjectInfo.getId());
                    //设置题目id，找到老的题目的id，是要通过考试id，科目id，题目code才能找到
                    oldexamStemInfoList.forEach(examStemInfo -> {
                        if (examStemInfo.getStemCode().equals(exchangeStem.getStemId()) && examStemInfo.getSubjectId().equals(exchangeSubjectInfo.getId())) {
                            enterpriseExamineeSubjectStemGrade.setStemId(examStemInfo.getId());
                        }
                    });
                    enterpriseExamineeSubjectStemGrade.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_N.getCode());
                    enterpriseExamineeSubjectStemGrade.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    enterpriseExamineeSubjectStemGrade.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    enterpriseExamineeSubjectStemGrade.setCreateTime(new Date());
                    enterpriseExamineeSubjectStemGrade.setUpdateTime(new Date());
                    enterpriseExamineeSubjectStemGrade.setQualifiedStatus("");
                    enterpriseExamineeSubjectStemGrade.setOfficeId(exchangeCandidate.getOfficeId());
                    enterpriseExamineeSubjectStemGrade.setDeptId(exchangeCandidate.getDeptId());
                    if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_1.getCode())) {
                        //普通科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_2.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode())) {
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_1.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(null);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_3.getCode())) {
                        //编程科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_3.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_5.getCode())) {
                        //单题计时卷科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_5.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    }

                    examineeSubjectGradeList.add(enterpriseExamineeSubjectStemGrade);
                }
            }
        });
    }

    /**
     * 获取科目下的题目信息
     *
     * @param exchangeCandidate
     * @param newExchangeSubjectInfo
     * @param examineeSubjectGradeList
     * @param saveExamStemInfo
     */
    private void getSubjectStemInfo(ExchangeCandidate exchangeCandidate, List<ExchangeSubjectInfo> newExchangeSubjectInfo, List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeList,
                                    List<EnterpriseExamineeSubjectGrade> examineeSubjectGradeListNoPersonality, List<ExamStemInfo> saveExamStemInfo) {
        newExchangeSubjectInfo.stream().forEach(exchangeSubjectInfo -> {
            // 获取科目的分数
            EnterpriseExamineeSubjectGrade enterpriseExamineeSubjectGrade = new EnterpriseExamineeSubjectGrade();
            enterpriseExamineeSubjectGrade.setId(IdUtils.generateId());
            enterpriseExamineeSubjectGrade.setExamId(exchangeCandidate.getExamId());
            enterpriseExamineeSubjectGrade.setExamineeId(exchangeCandidate.getCandidateId());
            enterpriseExamineeSubjectGrade.setSubjectId(exchangeSubjectInfo.getId());
            enterpriseExamineeSubjectGrade.setStemId("");
            enterpriseExamineeSubjectGrade.setUseTime(exchangeSubjectInfo.getPaperUseTime());

            enterpriseExamineeSubjectGrade.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_N.getCode());
            enterpriseExamineeSubjectGrade.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            enterpriseExamineeSubjectGrade.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            enterpriseExamineeSubjectGrade.setCreateTime(new Date());
            enterpriseExamineeSubjectGrade.setUpdateTime(new Date());
            enterpriseExamineeSubjectGrade.setQualifiedStatus("");
            enterpriseExamineeSubjectGrade.setOfficeId(exchangeCandidate.getOfficeId());
            enterpriseExamineeSubjectGrade.setDeptId(exchangeCandidate.getDeptId());
            if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_1.getCode())) {
                // 普通科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_2.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode())) {
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_1.getCode());
                enterpriseExamineeSubjectGrade.setScore(null);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_3.getCode())) {
                // 编程科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_3.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_5.getCode())) {
                //单题计时卷科目分数正常设置
                enterpriseExamineeSubjectGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_5.getCode());
                enterpriseExamineeSubjectGrade.setScore(exchangeSubjectInfo.getPapertScore());
                examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectGrade);
            }
            examineeSubjectGradeList.add(enterpriseExamineeSubjectGrade);

            if (CollectionUtils.isNotEmpty(exchangeSubjectInfo.getStemList())) {
                for (ExchangeStem exchangeStem : exchangeSubjectInfo.getStemList()) {
                    ExamStemInfo examStemInfo = new ExamStemInfo();
                    String stemId = IdUtils.generateId();
                    examStemInfo.setId(stemId);
                    examStemInfo.setStemCode(exchangeStem.getStemId());
                    examStemInfo.setName(exchangeStem.getStemName());
                    examStemInfo.setSubjectId(exchangeSubjectInfo.getId());
                    examStemInfo.setTitleNumber(0);
                    examStemInfo.setSort(0);
                    examStemInfo.setTotalPoints(new BigDecimal(0));
                    examStemInfo.setDeptId(exchangeCandidate.getDeptId());
                    examStemInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    examStemInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    examStemInfo.setCreateTime(new Date());
                    examStemInfo.setUpdateTime(new Date());
                    examStemInfo.setOfficeId(exchangeCandidate.getOfficeId());
                    saveExamStemInfo.add(examStemInfo);
                    // 获取题目的得分
                    EnterpriseExamineeSubjectGrade enterpriseExamineeSubjectStemGrade = new EnterpriseExamineeSubjectGrade();
                    enterpriseExamineeSubjectStemGrade.setId(IdUtils.generateId());
                    enterpriseExamineeSubjectStemGrade.setExamId(exchangeCandidate.getExamId());
                    enterpriseExamineeSubjectStemGrade.setExamineeId(exchangeCandidate.getCandidateId());
                    enterpriseExamineeSubjectStemGrade.setSubjectId(exchangeSubjectInfo.getId());
                    enterpriseExamineeSubjectStemGrade.setStemId(stemId);

                    enterpriseExamineeSubjectStemGrade.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_N.getCode());
                    enterpriseExamineeSubjectStemGrade.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    enterpriseExamineeSubjectStemGrade.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    enterpriseExamineeSubjectStemGrade.setCreateTime(new Date());
                    enterpriseExamineeSubjectStemGrade.setUpdateTime(new Date());
                    enterpriseExamineeSubjectStemGrade.setQualifiedStatus("");
                    enterpriseExamineeSubjectStemGrade.setOfficeId(exchangeCandidate.getOfficeId());
                    enterpriseExamineeSubjectStemGrade.setDeptId(exchangeCandidate.getDeptId());
                    if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_1.getCode())) {
                        // 普通科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_2.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode())) {
                        // INFO 性格科目分数正常为空,切不加入计算
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_1.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(null);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_3.getCode())) {
                        // 编程科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_3.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    } else if (exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_5.getCode())) {
                        // 单题计时卷科目分数正常设置
                        enterpriseExamineeSubjectStemGrade.setSubjectType(CommonEnums.SUBJECT_TYPE_5.getCode());
                        enterpriseExamineeSubjectStemGrade.setScore(exchangeStem.getStemScore());
                        examineeSubjectGradeListNoPersonality.add(enterpriseExamineeSubjectStemGrade);
                    }
                    examineeSubjectGradeList.add(enterpriseExamineeSubjectStemGrade);
                }
            }
        });
    }

    /**
     * 获取考试信息
     *
     * @param exchangeCandidate
     * @param newExchangeSubjectInfo
     * @param saveExamSubjectInfoList
     * @param saveExamSubjectNameConfigList
     */
    private void getExamSubjectInfo(ExchangeCandidate exchangeCandidate, List<ExchangeSubjectInfo> newExchangeSubjectInfo, List<ExamSubjectInfo> saveExamSubjectInfoList, List<ExamSubjectNameConfig> saveExamSubjectNameConfigList) {
        newExchangeSubjectInfo.stream().forEach(exchangeSubjectInfo -> {
            ExamSubjectInfo newexamSubjectInfo = new ExamSubjectInfo();
            newexamSubjectInfo.setId(exchangeSubjectInfo.getId());
            newexamSubjectInfo.setSubjectCode(exchangeSubjectInfo.getSubjectCode());
            newexamSubjectInfo.setExamInfoId(exchangeCandidate.getExamId());
            String subjectNameId = IdUtils.generateId();
            newexamSubjectInfo.setExamSubjectNameId(subjectNameId);
            newexamSubjectInfo.setPaperFullMarks(null != exchangeSubjectInfo.getPaperFullScore() ? exchangeSubjectInfo.getPaperFullScore() : BigDecimal.ZERO);
            newexamSubjectInfo.setComparisonType(CommonEnums.COMPARISON_TYPE_1.getCode());
            newexamSubjectInfo.setEligibilityCriteria(new BigDecimal("0"));
            newexamSubjectInfo.setDeptId(exchangeCandidate.getDeptId());
            newexamSubjectInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            newexamSubjectInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            newexamSubjectInfo.setCreateTime(new Date());
            newexamSubjectInfo.setUpdateTime(new Date());
            newexamSubjectInfo.setOfficeId(exchangeCandidate.getOfficeId());
            saveExamSubjectInfoList.add(newexamSubjectInfo);
            //获取要保存的科目的名称
            ExamSubjectNameConfig examSubjectNameConfig = new ExamSubjectNameConfig();
            examSubjectNameConfig.setId(subjectNameId);
            examSubjectNameConfig.setSubjectNameCode("");
            examSubjectNameConfig.setName(exchangeSubjectInfo.getSubjectName());
            examSubjectNameConfig.setDeptId(exchangeCandidate.getDeptId());
            examSubjectNameConfig.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            examSubjectNameConfig.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            examSubjectNameConfig.setCreateTime(new Date());
            examSubjectNameConfig.setUpdateTime(new Date());
            examSubjectNameConfig.setOfficeId(exchangeCandidate.getOfficeId());
            saveExamSubjectNameConfigList.add(examSubjectNameConfig);
        });
    }

    /**
     * 获取存在的科目和没有存在的科目,并判断是否存在性格测试卷
     *
     * @param exchangeCandidate
     * @param newExchangeSubjectInfo
     * @param oldExchangeSubjectInfo
     */
    private void getDistSubjectInfo(ExchangeCandidate exchangeCandidate, List<ExchangeSubjectInfo> newExchangeSubjectInfo,
                                    List<ExchangeSubjectInfo> oldExchangeSubjectInfo, List<ScoreLineItem> scoreLineItems) {
        List<ExchangeSubjectInfo> allExchangeSubjectInfo = exchangeCandidate.getSubjectInfo();
        List<String> idList = new ArrayList<>();
        // 计算主观题总分是各个科目的主观题分数之和
        BigDecimal subjectTotleScore = BigDecimal.ZERO;
        for (ExchangeSubjectInfo exchangeSubjectInfo : allExchangeSubjectInfo) {
            // 如果考试科目信息不是性格测试卷
            if (!exchangeSubjectInfo.getSubjectType().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_2.getCode())) {
                if (null != exchangeSubjectInfo.getPaperFullScore()) {
                    subjectTotleScore = subjectTotleScore.add(exchangeSubjectInfo.getPaperFullScore());
                }
            }
            idList.add(exchangeSubjectInfo.getSubjectCode());
        }
        exchangeCandidate.setSubjectTotleScore(subjectTotleScore);
        List<ExamSubjectInfo> existenceSubjectInfo = examSubjectInfoMapper.selectExistenceSubject(exchangeCandidate.getExamId(), idList);
        for (ExchangeSubjectInfo exchangeSubjectInfo : allExchangeSubjectInfo) {
            boolean existenceFlag = false;
            for (ExamSubjectInfo examSubjectInfo : existenceSubjectInfo) {
                if (exchangeSubjectInfo.getSubjectCode().equals(examSubjectInfo.getSubjectCode())) {
                    exchangeSubjectInfo.setId(examSubjectInfo.getId());
                    if (CollUtil.isNotEmpty(exchangeSubjectInfo.getStemList())) {
                        exchangeSubjectInfo.getStemList().forEach(exchangeStem -> {
                            exchangeStem.setSubjectId(examSubjectInfo.getId());
                        });
                    }
                    // 编程题没有试卷满分
                    if (!exchangeSubjectInfo.getSubjectType().toString().equals(CommonEnums.EXCHANGE_SUBJECT_TYPE_3.getCode())) {
                        // 这里比较获取科目中最大的满分试卷和合格标准分数
                        if (null != exchangeSubjectInfo.getPaperFullScore()
                                && null != examSubjectInfo.getPaperFullMarks()
                                && exchangeSubjectInfo.getPaperFullScore().compareTo(examSubjectInfo.getPaperFullMarks()) == -1) {
                            exchangeSubjectInfo.setPaperFullScore(examSubjectInfo.getPaperFullMarks());
                        }
                    }
                    exchangeSubjectInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
                    exchangeSubjectInfo.setUpdateTime(new Date());
                    oldExchangeSubjectInfo.add(exchangeSubjectInfo);
                    existenceFlag = true;
                    break;
                }
            }
            if (!existenceFlag) {
                String subjectId = IdUtils.generateId();
                exchangeSubjectInfo.setId(subjectId);
                newExchangeSubjectInfo.add(exchangeSubjectInfo);
            }
        }

        // 获取科目的复合分数数据
        allExchangeSubjectInfo.stream().forEach(exchangeSubjectInfo -> {
            ScoreLineItem scoreLineItem = new ScoreLineItem();
            scoreLineItem.setSubjectId(exchangeSubjectInfo.getId());
            scoreLineItem.setSubjectName(exchangeSubjectInfo.getSubjectName());
            BigDecimal papertScore = exchangeSubjectInfo.getPapertScore();
            if (papertScore != null) {
                scoreLineItem.setScore(papertScore.toString());
            }
            scoreLineItems.add(scoreLineItem);
        });
    }


    /**
     * 封装要更新的考试信息
     *
     * @param exchangeCandidate
     * @param resultEntity
     */
    private ExamInfo getUpdataExamInfo(ExchangeCandidate exchangeCandidate, LocalDateTime examStartTime,LocalDateTime examEndTime,  ExamInfo examInfo) {
        ExamInfo currExamInfo = new ExamInfo();
        currExamInfo.setId(examInfo.getId());
        currExamInfo.setYear(String.valueOf(examStartTime.getYear())); 
        currExamInfo.setExamStartDay(examStartTime);
        currExamInfo.setExamEndDay(examEndTime);
        currExamInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        currExamInfo.setUpdateTime(new Date());
        currExamInfo.setTaskId(exchangeCandidate.getTaskId());
        currExamInfo.setOfficeId(exchangeCandidate.getOfficeId());
        long useTime = 0;
        for (ExchangeSubjectInfo exchangeSubjectInfo : exchangeCandidate.getSubjectInfo()) {
            useTime += exchangeSubjectInfo.getPaperTimeLength();
        }
        currExamInfo.setUseTime(useTime);
        currExamInfo.setSignNumber(exchangeCandidate.getTimeCandidateCounts());
        return currExamInfo;
    }

    /**
     * 封装要更新考试名称信息
     *
     * @param examInfo
     * @param resultEntity
     */
    private ExamNameConfig getUpdateExamNameConfig(ExamInfo examInfo, String examName, ExchangeCandidate exchangeCandidate) {
        ExamNameConfig examNameConfig = new ExamNameConfig();
        examNameConfig.setExamNameCode(examInfo.getExamNameConfigId());
        examNameConfig.setExamType(exchangeCandidate.getTestClassify());
        examNameConfig.setDeptId(Long.getLong(CommonEnums.DEPT_ID_DEFAULT.getCode()));
        examNameConfig.setId(examInfo.getExamNameConfigId());
        examNameConfig.setName(examName);
        examNameConfig.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        examNameConfig.setUpdateTime(new Date());
        examNameConfig.setOfficeId(exchangeCandidate.getOfficeId());
        return examNameConfig;
    }

    /**
     * 封装要保存的考试信息类
     *
     * @param exchangeCandidate
     * @param resultEntity
     * @param examNameConfigId
     */
    private ExamInfo getExamInfo(ExchangeCandidate exchangeCandidate, LocalDateTime examStartTime,LocalDateTime examEndTime, String examNameConfigId) {
        ExamInfo currExamInfo = new ExamInfo();
        currExamInfo.setId(exchangeCandidate.getExamId());
        currExamInfo.setExamCode(exchangeCandidate.getExamCode());
        currExamInfo.setExamNameConfigId(examNameConfigId);
        currExamInfo.setYear(String.valueOf(examStartTime.getYear()));
        currExamInfo.setExamType(exchangeCandidate.getTestClassify());
        currExamInfo.setExamStartDay(examStartTime);
        currExamInfo.setExamEndDay(examEndTime);
        currExamInfo.setOrigin(CommonEnums.ORIGIN_1.getCode());
        currExamInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        currExamInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        currExamInfo.setCreateTime(new Date());
        currExamInfo.setUpdateTime(new Date());
        currExamInfo.setOfficeId(exchangeCandidate.getOfficeId());
        currExamInfo.setDeptId(StrUtil.isNotBlank(exchangeCandidate.getExamDeptId()) ? exchangeCandidate.getExamDeptId() : exchangeCandidate.getDeptId());
        currExamInfo.setTaskId(exchangeCandidate.getTaskId());
        long useTime = 0;
        for (ExchangeSubjectInfo exchangeSubjectInfo : exchangeCandidate.getSubjectInfo()) {
            useTime += exchangeSubjectInfo.getPaperTimeLength();
        }
        currExamInfo.setUseTime(useTime);
        currExamInfo.setSignNumber(exchangeCandidate.getTimeCandidateCounts());
        return currExamInfo;
    }

    /**
     * 封装要保存的考试名称信息类
     *
     * @param resultEntity
     * @param examNameConfigId
     */
    private ExamNameConfig getUpdateExamNameConfig(String examName, String examNameConfigId, ExchangeCandidate exchangeCandidate) {
        ExamNameConfig examNameConfig = new ExamNameConfig();
        examNameConfig.setId(examNameConfigId);
        examNameConfig.setName(examName);
        examNameConfig.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        examNameConfig.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        examNameConfig.setCreateTime(new Date());
        examNameConfig.setUpdateTime(new Date());
        examNameConfig.setOfficeId(exchangeCandidate.getOfficeId());
        return examNameConfig;
    }
    
    


    /**
     * 封装考生的所有信息数据
     *
     * @param exchangeCandidate
     * @param examinee
     * @param candidateConfigs
     * @param candidateInfos
     */
    private void getCandidateAllData(ExchangeCandidate exchangeCandidate, EnterpriseExamineeInfo examinee,
                                     List<CandidateConfig> candidateConfigs, List<CandidateInfo> candidateInfos) {


        List<ExchangeCandidateConfig> exchangeCandidateConfigs = exchangeCandidate.getCandidateConfig();
        List<ExchangeCandidateInfo> exchangeCandidateInfos = exchangeCandidate.getCandidateInfo();
        //检查考生信息是否一一配对
        checkConfigAndValue(exchangeCandidateConfigs, exchangeCandidateInfos);

        exchangeCandidateConfigs.stream().forEach(exchangeCandidateConfig -> {
            CandidateConfig candidateInfo = new CandidateConfig();
            candidateInfo.setId(exchangeCandidateConfig.getCode());
            candidateInfo.setExamineeId(exchangeCandidate.getCandidateId());
            candidateInfo.setName(exchangeCandidateConfig.getName());
            candidateInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            candidateInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            candidateInfo.setCreateTime(new Date());
            candidateInfo.setUpdateTime(new Date());
            candidateInfo.setOfficeId(exchangeCandidate.getOfficeId());
            candidateInfo.setDeptId(exchangeCandidate.getDeptId());
            candidateConfigs.add(candidateInfo);
        });

        exchangeCandidateInfos.stream().forEach(exchangeCandidateInfo -> {
            CandidateInfo candidateInfo = new CandidateInfo();
            candidateInfo.setId(IdUtils.generateId());
            candidateInfo.setExamId(exchangeCandidate.getExamId());
            candidateInfo.setExamineeId(exchangeCandidate.getCandidateId());
            candidateInfo.setConfigCode(exchangeCandidateInfo.getConfigCode());
            candidateInfo.setConfigValue(exchangeCandidateInfo.getConfigValue());
            candidateInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            candidateInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
            candidateInfo.setCreateTime(new Date());
            candidateInfo.setUpdateTime(new Date());
            candidateInfo.setOfficeId(exchangeCandidate.getOfficeId());
            candidateInfo.setDeptId(exchangeCandidate.getDeptId());
            for (ExchangeCandidateConfig exchangeCandidateConfig : exchangeCandidateConfigs) {
                if (exchangeCandidateInfo.getConfigCode().equals(exchangeCandidateConfig.getCode())) {
                    candidateInfo.setOrderNum(exchangeCandidateConfig.getOrderNum());
                    String typeCode = ExchangeValTypeEnum.getValue(exchangeCandidateConfig.getType());
                    candidateInfo.setType(typeCode);
                }
            }
            candidateInfos.add(candidateInfo);
        });

        //如果是性别、学历、专业要从我们这边的数据字典表中匹配数据；如果存在在枚举中的对应关系，使用反射给字段加上学生的值

        Map<String, String> sexDataMap = dictDataService.selectDictDataMap("sys_user_sex", "V");
        Map<String, String> educationDataMap = dictDataService.selectDictDataMap("education", "V");
        Map<String, String> subjectDataMap = dictDataService.selectDictDataMap("subject", "V");

        exchangeCandidateConfigs.stream().forEach(exchangeCandidateConfig -> {

            String code = exchangeCandidateConfig.getCode();
            //如果是性别、学历、专业要从我们这边的数据字典表中匹配数据  （这样一点都不灵活了！）
            if ("性别".equals(exchangeCandidateConfig.getName())) {
                for (ExchangeCandidateInfo exchangeCandidateInfo : exchangeCandidateInfos) {
                    if (code.equals(exchangeCandidateInfo.getConfigCode())) {
                        String value = sexDataMap.get(exchangeCandidateInfo.getConfigValue());
                        examinee.setSex(value);
                        break;
                    }
                }
            }
            if ("学历".equals(exchangeCandidateConfig.getName())) {
                for (ExchangeCandidateInfo exchangeCandidateInfo : exchangeCandidateInfos) {
                    if (code.equals(exchangeCandidateInfo.getConfigCode())) {
                        String value = educationDataMap.get(exchangeCandidateInfo.getConfigValue());
                        examinee.setEducation(value);
                        break;
                    }
                }
            }
            if ("专业".equals(exchangeCandidateConfig.getName())) {
                for (ExchangeCandidateInfo exchangeCandidateInfo : exchangeCandidateInfos) {
                    if (code.equals(exchangeCandidateInfo.getConfigCode())) {
                        String value = subjectDataMap.get(exchangeCandidateInfo.getConfigValue());
                        examinee.setMajor(value);
                        break;
                    }
                }
            }

            //如果存在在枚举中的对应关系，使用反射给字段加上学生的值
            String fieldName = ExchangeNameEnum.getValue(exchangeCandidateConfig.getName());
            if (fieldName != null) {
                String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                exchangeCandidateInfos.stream().forEach(candidateInfo1 -> {
                    if (code.equals(candidateInfo1.getConfigCode())) {
                        try {
                            //限制考试系统自己填写字段的长度，超出长度不进行插入到考生表字段中
                            if ("idcard".equals(fieldName) && candidateInfo1.getConfigValue().length() < 50) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue());
                            } else if ("idcard".equals(fieldName)) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue().substring(0, 46) + "...");
                            }

                            if ("name".equals(fieldName) && candidateInfo1.getConfigValue().length() < 21) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue());
                            } else if ("name".equals(fieldName)) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue().substring(0, 16) + "...");
                            }

                            if ("admissionNo".equals(fieldName) && candidateInfo1.getConfigValue().length() < 50) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue());
                            } else if ("admissionNo".equals(fieldName)) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue().substring(0, 46) + "...");
                            }

                            if ("mobile".equals(fieldName) && candidateInfo1.getConfigValue().length() < 13) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue());
                            } else if ("mobile".equals(fieldName)) {
                                Method method = examinee.getClass().getMethod(methodName, String.class);
                                method.invoke(examinee, candidateInfo1.getConfigValue().substring(0, 9) + "...");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }

    /**
     * 封装考生对象
     *
     * @param exchangeCandidate
     * @return
     */
    private EnterpriseExamineeInfo getExaminee(ExchangeCandidate exchangeCandidate) {
        EnterpriseExamineeInfo enterpriseExamineeInfo = new EnterpriseExamineeInfo();
        enterpriseExamineeInfo.setId(exchangeCandidate.getCandidateId());
        enterpriseExamineeInfo.setExamId(exchangeCandidate.getExamId());
        enterpriseExamineeInfo.setAdmissionNo(exchangeCandidate.getAdmissionNo());
        enterpriseExamineeInfo.setArchivedStatus(CommonEnums.ARCHIVED_STATUS_N.getCode());
        enterpriseExamineeInfo.setOrigin(Integer.valueOf(CommonEnums.ORIGIN_1.getCode()));
        // 这里获取的是评卷时间
        enterpriseExamineeInfo.setUseTime(exchangeCandidate.getUseTime());
        enterpriseExamineeInfo.setCreateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        enterpriseExamineeInfo.setUpdateBy(CommonEnums.SYS_USER_ADMIN.getCode());
        enterpriseExamineeInfo.setCreateTime(new Date());
        enterpriseExamineeInfo.setUpdateTime(new Date());
        enterpriseExamineeInfo.setBeginTime(exchangeCandidate.getBeginTime());
        enterpriseExamineeInfo.setKeepHighestScore(exchangeCandidate.getKeepHighestScore());
        enterpriseExamineeInfo.setOfficeId(exchangeCandidate.getOfficeId());
        enterpriseExamineeInfo.setDeptId(exchangeCandidate.getDeptId());
        enterpriseExamineeInfo.setProvinceCode(exchangeCandidate.getProvinceCode());
        enterpriseExamineeInfo.setCityCode(exchangeCandidate.getCityCode());
        enterpriseExamineeInfo.setCountryCode(exchangeCandidate.getCountryCode());
        enterpriseExamineeInfo.setRoomId(exchangeCandidate.getPlaceId());
        enterpriseExamineeInfo.setRoomName(exchangeCandidate.getPlaceName());
        return enterpriseExamineeInfo;
    }

    /**
     * 校验学生的信息是否一一匹配
     *
     * @param exchangeCandidateConfigs
     * @param exchangeCandidateInfos
     */
    private void checkConfigAndValue(List<ExchangeCandidateConfig> exchangeCandidateConfigs, List<ExchangeCandidateInfo> exchangeCandidateInfos) {
        exchangeCandidateConfigs.stream().forEach(exchangeCandidateConfig -> {
            AtomicBoolean flag = new AtomicBoolean(false);
            exchangeCandidateInfos.stream().forEach(exchangeCandidateInfo -> {
                if (exchangeCandidateInfo.getConfigCode().equals(exchangeCandidateConfig.getCode()))
                    flag.set(true);
            });
            if (!flag.get()) {
                throw new CustomException("学生的信息配置内容不匹配", 500);
            }
        });
    }
}
